﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Globalization;
using System.Web;

namespace Pixysoft.Framework.Logs
{
    class StringHelper
    {
        public static bool testdriven_fakeid = false;

        public static int log_capacity = 1024 * 1024 * 1; // 1 mb

        public static int log_reportspan = 3000;//+- 3000 m sec

        public static int default_log_capacity = 1024 * 1024 * 1; // 1 mb

        public static string default_log_filepath = StringFilter.RegularPath(AppDomain.CurrentDomain.BaseDirectory) + @"log\";



        public const string global_configuartion_configname = "LogConfiguration";

        public const string global_framework_id = "pixysoft.framework.log";



        public static string default_log_postfix = ".log";

        public static string default_log_prefix = "pixysoft";

        public static string default_compress_postfix = ".gzip";



        public static string default_log_dateformat = "yyyy-MM-dd HH:mm:ss:fff";

        public static string default_log_pack_dateformat = "yyyyMMddHHmmssfff";



        public static string default_element_log = "log";

        public static string default_element_document = "document";

        public static string default_element_report = "report";

        public static string default_element_filepath = "filepath";

        public static string default_element_filename = "filename";

        public static string default_element_framedocument = "framedocument";

        public static string default_element_frame = "frame";

        public static string default_element_message = "message";

        public static string default_attribute_dll = "dll";

        public static string default_attribute_class = "class";

        public static string default_attribute_method = "method";

        public static string default_attribute_file = "file";

        public static string default_attribute_path = "path";

        public static string default_attribute_column = "column";

        public static string default_attribute_line = "line";

        public static string default_attribute_il = "il";

        public static string default_attribute_filepath = "filepath";


        public static string default_attribute_timespan = "timespan";

        public static string default_attribute_timefrom = "timefrom";

        public static string default_attribute_timeto = "timeto";

        public static string default_attribute_id = "id";

        public static string default_attribute_ip = "ip";

        public static string default_attribute_level = "level";

        public static string default_attribute_time = "time";

        public static string default_attribute_module = "module";



        public static string default_tag_frame = "<frame class=\"{0}\" method=\"{1}\" dll=\"{2}\" file=\"{3}\" il=\"{4}\" line=\"{5}\" column=\"{6}\" id=\"{7}\"/>";

        public static string default_tag_log = "<log dll=\"{0}\" file=\"{1}\" path=\"{2}\"/>";



        public static string GetLogLevelString(LogLevel level)
        {
            switch (level)
            {
                case LogLevel.DEBUG:
                    return LogLevelCollection.DEBUG;
                case LogLevel.ERROR:
                    return LogLevelCollection.ERROR;
                case LogLevel.FATAL:
                    return LogLevelCollection.FATAL;
                case LogLevel.INFO:
                    return LogLevelCollection.INFO;
                case LogLevel.ALL:
                case LogLevel.OFF:
                default:
                    return LogLevelCollection.OTHER;
            }
        }

        public static LogLevel GetLogLevel(string level)
        {
            if (string.IsNullOrEmpty(level))
                return LogLevel.OFF;

            if (level.Equals(LogLevelCollection.INFO, StringComparison.OrdinalIgnoreCase))
                return LogLevel.INFO;

            if (level.Equals(LogLevelCollection.FATAL, StringComparison.OrdinalIgnoreCase))
                return LogLevel.FATAL;

            if (level.Equals(LogLevelCollection.ERROR, StringComparison.OrdinalIgnoreCase))
                return LogLevel.ERROR;

            if (level.Equals(LogLevelCollection.DEBUG, StringComparison.OrdinalIgnoreCase))
                return LogLevel.DEBUG;

            if (level.Equals(LogLevelCollection.WARN, StringComparison.OrdinalIgnoreCase))
                return LogLevel.WARN;

            return LogLevel.ALL;
        }

        public static bool TryParseFileSequence(string filename, out DateTime time)
        {
            time = DateTime.MinValue;

            if (string.IsNullOrEmpty(filename))
                return false;

            string sequence = Regex.Match(filename, "[\\d]{17}", RegexOptions.IgnoreCase).Value;

            if (string.IsNullOrEmpty(sequence))
                return false;

            if (!DateTime.TryParseExact(sequence, default_log_pack_dateformat, CultureInfo.InvariantCulture, DateTimeStyles.None, out time))
                return false;

            return true;
        }

        public static string RegularLogContent(string log)
        {
            //10-02-06 http://www.aspxcs.net/HTML/165234367.html

            if (string.IsNullOrEmpty(log))
                return log;

            StringBuilder builder = new StringBuilder();

            foreach (char singlelog in log)
            {
                //http://www.cnblogs.com/sunrack/articles/799707.html 过滤ascii码

                if (singlelog == '\r')
                    builder.Append(singlelog);

                else if (singlelog == '\n')
                    builder.Append(singlelog);

                else if (singlelog == '\t')
                    builder.Append(singlelog);

                else if (singlelog == 27) // esc
                    builder.Append('?');

                else if (singlelog == '<') // <
                    builder.Append('(');

                else if (singlelog == '>')
                    builder.Append(')');

                else if (singlelog == '"')
                    builder.Append('^');

                else if (singlelog == '\'')
                    builder.Append('^');

                else if (singlelog == '&')
                    builder.Append('$');

                else if (singlelog >= 32 && singlelog <= 126)
                    builder.Append(singlelog);

                    //http://www.cnblogs.com/jackhuclan/archive/2008/07/28/1254443.html
                //在unicode 字符串中，中文的范围是在4E00..9FFF:CJK Unified Ideographs。

                else if (singlelog >= 0x4e00 && singlelog <= 0x9fff)
                    builder.Append(singlelog);

                else
                    builder.Append('?');// ? 
            }

            return builder.ToString();
        }

        internal static string RegularLogAttribute(string log)
        {
            if (string.IsNullOrEmpty(log))
                return log;

            StringBuilder builder = new StringBuilder();

            foreach (char singlelog in log)
            {
                //http://www.cnblogs.com/sunrack/articles/799707.html 过滤ascii码

                if (singlelog == '\r')
                {
                    //builder.Append(singlelog);
                }

                else if (singlelog == '\n')
                {
                    //builder.Append(singlelog);
                }

                else if (singlelog == '\t')
                {
                    //builder.Append(singlelog);
                }

                else if (singlelog == 27) // esc
                    builder.Append('?');

                else if (singlelog == '<') // <
                    builder.Append('(');

                else if (singlelog == '>')
                    builder.Append(')');

                else if (singlelog == '&')
                    builder.Append('$');

                else if (singlelog >= 32 && singlelog <= 126)
                    builder.Append(singlelog);

                    //http://www.cnblogs.com/jackhuclan/archive/2008/07/28/1254443.html
                //在unicode 字符串中，中文的范围是在4E00..9FFF:CJK Unified Ideographs。

                else if (singlelog >= 0x4e00 && singlelog <= 0x9fff)
                    builder.Append(singlelog);

                else
                    builder.Append('?');// ? 
            }

            return builder.ToString();
        }



        public static DateTime GetDateTime()
        {
            return Pixysoft.Tools.GlobalTimer.Instance.GetGlobalTime();
        }

        public static string GetRawDateTime()
        {
            DateTime now = GetDateTime();

            return GetRawDateTime(now);
        }

        public static string GetRawDateTime(DateTime now)
        {
            return now.ToString(StringHelper.default_log_dateformat);// ToString("yyyy-MM-dd HH:mm:ss:") + now.Millisecond.ToString("000");
        }

        public static string GetIp()
        {
            //09-12-13 如果设置不恰当，这里会出现空指针
            try
            {
                return HttpContext.Current.Request.UserHostAddress;
            }
            catch
            {
                throw new Exception("cannot get ip from localmachine. please check config.");
            }
        }

        public static string GetId()
        {
            if (testdriven_fakeid)
                return "000-000-000";

            return Guid.NewGuid().ToString().ToLower();
        }
    }

    class LogLevelCollection
    {
        public static LogLevel GetLogLevel(string value)
        {
            if (INFO.Equals(value, StringComparison.OrdinalIgnoreCase))
                return LogLevel.INFO;
            if (ERROR.Equals(value, StringComparison.OrdinalIgnoreCase))
                return LogLevel.ERROR;
            if (WARN.Equals(value, StringComparison.OrdinalIgnoreCase))
                return LogLevel.WARN;
            if (DEBUG.Equals(value, StringComparison.OrdinalIgnoreCase))
                return LogLevel.DEBUG;
            if (FATAL.Equals(value, StringComparison.OrdinalIgnoreCase))
                return LogLevel.FATAL;
            return LogLevel.ALL;
        }

        public const string INFO = "info";
        public const string ERROR = "error";
        public const string WARN = "warn";
        public const string DEBUG = "debug";
        public const string FATAL = "fatal";

        public const string OTHER = "other";
    }
}

